#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <pthread.h>

using namespace std;

//线程锁
pthread_mutex_t mutex;

int tickets = 10000;

void *RobTicket(void *arg)
{
  string name = static_cast<const char*>(arg);

  int num = 0;
  while(true)
  {
    pthread_mutex_lock(&mutex); //上锁
    if(tickets > 0)
    {
      usleep(2000);
      cout << "线程 " << name << " 已经成功抢到了一张票: " << tickets-- << endl;
      num++;
      pthread_mutex_unlock(&mutex); //解锁
    }
    else
    {
      pthread_mutex_unlock(&mutex); //解锁
      break;
    }

    usleep(1000); //解锁后，做一些事，避免出现 竞争锁
  }

  pthread_exit((void*)num);
}

//简易抢票器，演示互斥锁的作用
int main()
{
  int n = 3;
  pthread_t arr[n]; //三个抢票次线程

  //初始化锁
  pthread_mutex_init(&mutex, nullptr);

  for(int i = 0; i < n; i++)
  {
    char* buff = new char[64];
    snprintf(buff, 64, "thread<--->%d", i + 1);
    pthread_create(&arr[i], nullptr, RobTicket, (void*)buff);
    //pthread_detach(arr[i]); //线程分离，专注于抢票
    usleep(1000);
  }

  for(int i = 0; i < n; i++)
  {
    void* retval = nullptr;
    int ret = pthread_join(arr[i], &retval);
    if(ret != 0) cout << "线程未结束" << endl;
    else
    {
      usleep(1000);
      cout << "========================================" << endl;
      cout << "线程 " << i << " 共计抢了：" << (uint64_t)retval << "张票" << endl;
    }
  }

  cout << "所有票已被抢完！" << endl;

  //销毁锁
  pthread_mutex_destroy(&mutex);

  return 0;
}

// int g_val = 668;  //全局变量
// //__thread int g_val = 668;  //修饰后，不再位于全局区，而是位于局部存储区中

// void *threadRoutine(void *args)
// {
//   int val = 0;  //不同线程中的局部变量位于其独立栈中

//   int n = 5;
//   while(n--)
//   {
//     //cout << "val: " << val++ << "<--->" << "&val: " << &val << endl;
//     cout << "g_val: " << g_val++ << "<--->" << "&g_val: " << &g_val << endl;
//     sleep(1);
//   }

//   pthread_exit((void*)668);
// }

// int main()
// {
//   //多线程中的局部变量 与 全局变量问题

//   pthread_t arr[5];
//   for(int i = 0; i < 5; i++)
//   {
//     //创建一批线程
//     char* buff = new char[64];
//     snprintf(buff, 64, "thrad: %d", i);
//     pthread_create(&arr[i], nullptr, threadRoutine, (void*)buff);
//     usleep(1000);
//   }

//   void* retval;
//   for(int i = 0; i < 5; i++)
//   {
//     int ret = pthread_join(arr[i], &retval);
//     if(ret != 0) cout << "pthread_join fail" << endl;
//   }

//   cout << "所有线程已被回收" << " 回收码：" << (uint64_t)retval << endl;

//   return 0;
// }

// int main()
// {
//   pthread_t arr[5];
//   for(int i = 0; i < 5; i++)
//   {
//     //创建一批线程
//     char* buff = new char[64];
//     snprintf(buff, 64, "thrad: %d", i);
//     pthread_create(&arr[i], nullptr, threadRoutine, (void*)buff);
//     usleep(1000);
//   }

//   void* retval;
//   for(int i = 0; i < 5; i++)
//   {
//     int ret = pthread_join(arr[i], &retval);
//     if(ret != 0) cout << "pthread_join fail" << endl;
//   }

//   cout << "所有线程已被回收" << " 回收码：" << (uint64_t)retval << endl;

//   return 0;
// }

// void *threadRoutine(void *arg)
// {
//   pthread_detach(pthread_self()); //自己分离自己

//   string name = static_cast<char*>(arg);
//   int cnt = 5;
//   while(cnt--)
//   {
//     cout << "线程 " << name << " 正在运行" << endl;
//     sleep(1);
//   }

//   pthread_exit((void*)668);
// }

// int main()
// {
//   //创建一个线程，并 join 等待
//   //将线程分离后，再观察现象
//   pthread_t id;
//   pthread_create(&id, nullptr, threadRoutine, (void*)"thread 1" );
//   sleep(1);
//   //pthread_detach(id); //线程被分离后，再次 join 次线程会报错

//   //主线程等待次线程退出
//   void *retval = nullptr;
//   int ret = pthread_join(id, &retval);
//   if(ret != 0) cout << "error: " << ret << " | " << strerror(ret) << " pthread_join fail! errno: " << (uint64_t)retval << endl;
  
//   sleep(10);
  
//   return 0;
// }
